﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Sisocana.Core;
using Sisocana.Core.Models;
using Sisocana.Core.Interfaces;
using Sisocana.Dal.EntityModels;
using Sisocana.Dal;
using Sisocana.Dal.Interfaces;
using System.Data;


namespace Sisocana.Core
{
    public class ONGDefinidaService : ServiceBase<IONGDefinidaModel>, IONGDefinidaService
    {
        public ONGDefinidaService()
            : this(new ONGDefinidaRepository(), new DireccionRepository())
        {
        }
        private IONGDefinidaRepository _ONGDefinidaRepository;
        private IDireccionRepository _DireccionRepository;

        public ONGDefinidaService(IONGDefinidaRepository ONGDefinidaRepository, IDireccionRepository DireccionRepository)
        {
            _ONGDefinidaRepository = ONGDefinidaRepository ?? new ONGDefinidaRepository();
            _DireccionRepository = DireccionRepository ?? new DireccionRepository();
        }

        public void createONGDefinidaMapperEF2Model()
        {
            AutoMapper.Mapper.CreateMap<ONGDefinida, ONGDefinidaModel>()
                .ForMember(s => s.Ciudad, opt => opt.MapFrom(c => c.Direccion.Ciudad.Trim()))
                .ForMember(s => s.CoordX, opt => opt.MapFrom(c => c.Direccion.CoordX.Trim()))
                .ForMember(s => s.CoordY, opt => opt.MapFrom(c => c.Direccion.CoordY.Trim()))
                .ForMember(s => s.CP, opt => opt.MapFrom(c => c.Direccion.CP.Trim()))
                .ForMember(s => s.Dir, opt => opt.MapFrom(c => c.Direccion.Dir.Trim()))
                .ForMember(s => s.Estado, opt => opt.MapFrom(c => c.Direccion.Estado.Trim()))
                .ForMember(s => s.nombreONGDefinida, opt => opt.MapFrom(c => c.nombreONGDefinida.Trim()))
                .ForMember(s => s.Pais, opt => opt.MapFrom(c => c.Direccion.Pais.Trim()))
                .ForMember(s => s.paypalLogin, opt => opt.MapFrom(c => c.paypalLogin.Trim()))
                .ForMember(s => s.paypalPartner, opt => opt.MapFrom(c => c.paypalPartner.Trim()))
                .ForMember(s => s.telefono, opt => opt.MapFrom(c => c.telefono.Trim()))
                .ForMember(s => s.sitioId, opt => opt.MapFrom(c => c.Sitio.id))
                .ForMember(s => s.ongName, opt => opt.MapFrom(c => c.ONG.nombre.Trim()))
                .ForMember(s => s.estadoONGGeneral, opt => opt.MapFrom(c => c.ONG.estado.Trim()));
        }

        public void createONGDefinidaMapperModel2EF()
        {
            AutoMapper.Mapper.CreateMap<ONGDefinidaModel, ONGDefinida>()
                .ForMember(s => s.Sitio.id, opt => opt.MapFrom(c => c.sitioId))
                .ForMember(s => s.ONG.nombre, opt => opt.MapFrom(c => c.ongName));
        }

        public void createDireccionMapperEF2Model()
        {
            AutoMapper.Mapper.CreateMap<Direccion, DireccionModel>()
                .ForMember(s => s, opt => opt.MapFrom(c => c.Ciudad));
        }

        public void createDireccionMapperModel2EF()
        {
            AutoMapper.Mapper.CreateMap<DireccionModel, Direccion>();
        }

        public int createONGDefinida(ONGDefinidaModel ong)
        {


            Direccion dirAdd = new Direccion();
            dirAdd.Ciudad = ong.Ciudad;
            dirAdd.CoordX = ong.CoordX;
            dirAdd.CoordY = ong.CoordY;
            dirAdd.CP = ong.CP;
            dirAdd.Dir = ong.Dir;
            dirAdd.Estado = ong.Estado;
            dirAdd.Pais = ong.Pais;

            SiteRepository sitios = new SiteRepository();
            Sitio sit = sitios.GetSingle(o => o.id == ong.sitioId);

            ONGRepository ongs = new ONGRepository();
            ONG ongEF = ongs.GetSingle(a => a.nombre == ong.ongName);

            ONGDefinida ins = new ONGDefinida();
            ins.estadoDefinido = "A";
            ins.nombreONGDefinida = ong.nombreONGDefinida;
            ins.paypalLogin = ong.paypalLogin;
            ins.paypalPartner = ong.paypalPartner;
            ins.telefono = ong.telefono;

            ins.Direccion = dirAdd;
            dirAdd.ONGDefinida = ins;

            ins.ONG = ongEF;
            ongEF.ONGDefinida.Add(ins);

            ins.Sitio = sit;

            dirAdd.Sitio.Add(sit);
            sit.Direccion.Add(dirAdd);

            try
            {
                _DireccionRepository.Add(dirAdd);
                _ONGDefinidaRepository.Add(ins);
                _ONGDefinidaRepository.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }
        }

        public int updateONGDefinida(ONGDefinidaModel ong)
        {
            ONGDefinida find = _ONGDefinidaRepository.GetSingle(o => o.id == ong.id);
            if (find == null)
                return -1;

            if (find.ONG.nombre.Trim() != ong.ongName.Trim())
            {
                ONGRepository ongs = new ONGRepository();
                ONG ongEF = ongs.GetSingle(a => a.nombre == ong.ongName);
                find.ONG = ongEF;
            }

            find.nombreONGDefinida = ong.nombreONGDefinida;
            find.paypalLogin = ong.paypalLogin;
            find.paypalPartner = ong.paypalPartner;
            find.telefono = ong.telefono;
            find.Direccion.CoordX = ong.CoordX;
            find.Direccion.CoordY = ong.CoordY;
            find.Direccion.CP = ong.CP;
            find.Direccion.Dir = ong.Dir;
            find.Direccion.Estado = ong.Estado;
            find.Direccion.Pais = ong.Pais;
            try
            {
                _ONGDefinidaRepository.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }
        }

        public int changeStateONGDefinida(int id)
        {
            ONGDefinida find = _ONGDefinidaRepository.GetSingle(o => o.id == id);
            if (find == null)
                return -1;

            if (find.estadoDefinido == "A")
                find.estadoDefinido = "I";
            else
                find.estadoDefinido = "A";

            try
            {
                _ONGDefinidaRepository.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }
        }


      public ONGDefinidaModel GetSingle(Expression<Func<ONGDefinidaModel, bool>> whereCondition)
        {
            createONGDefinidaMapperEF2Model();

            IList<ONGDefinida> ONGsEF = _ONGDefinidaRepository.GetAll();
            List<ONGDefinidaModel> ONGS = new List<ONGDefinidaModel>();

            ONGS = AutoMapper.Mapper.Map(ONGsEF, ONGS);

            IQueryable<ONGDefinidaModel> ONGRet = ONGS.AsQueryable<ONGDefinidaModel>().Where(whereCondition);

            List<ONGDefinidaModel> ret = ONGRet.ToList();

            if (ret.Count == 0)
                return null;
            ONGDefinidaModel ong = ret.First();
            ONGDefinida ONGEF = _ONGDefinidaRepository.GetSingle(a => a.id == ong.id);
            ong.Ciudad = ONGEF.Direccion.Ciudad;
            ong.CoordX = ONGEF.Direccion.CoordX;
            ong.CoordY = ONGEF.Direccion.CoordY;
            ong.CP = ONGEF.Direccion.CP;
            ong.Dir = ONGEF.Direccion.Dir;
            ong.Estado = ONGEF.Direccion.Estado;
            ong.Pais = ONGEF.Direccion.Pais;

            return ong;
        }

        public void Add(ONGDefinidaModel entity)
        {
            throw new NotImplementedException();
        }

        public void Delete(ONGDefinidaModel entity)
        {
            throw new NotImplementedException();
        }

        public void Update(ONGDefinidaModel entity)
        {
            throw new NotImplementedException();
        }

        public IList<ONGDefinidaModel> GetAll(Expression<Func<ONGDefinidaModel, bool>> whereCondition)
        {
            createONGDefinidaMapperEF2Model();

            IList<ONGDefinida> ONGsEF = _ONGDefinidaRepository.GetAll();
            List<ONGDefinidaModel> ONGS = new List<ONGDefinidaModel>();

            //ONGS = AutoMapper.Mapper.Map(ONGsEF, ONGS);
            foreach (ONGDefinida ONGEF in ONGsEF)
            {
                ONGDefinidaModel ong = new ONGDefinidaModel();
                ong = AutoMapper.Mapper.Map(ONGEF, ong);

                ong.Ciudad = ONGEF.Direccion.Ciudad;
                ong.CoordX = ONGEF.Direccion.CoordX;
                ong.CoordY = ONGEF.Direccion.CoordY;
                ong.CP = ONGEF.Direccion.CP;
                ong.Dir = ONGEF.Direccion.Dir;
                ong.Estado = ONGEF.Direccion.Estado;
                ong.Pais = ONGEF.Direccion.Pais;
                
                ONGS.Add(ong);
            }
            IQueryable<ONGDefinidaModel> ONGRet = ONGS.AsQueryable<ONGDefinidaModel>().Where(whereCondition);

            List<ONGDefinidaModel> ret = ONGRet.ToList();

            return ret;

        }

        public IList<ONGDefinidaModel> GetAll()
        {
            createONGDefinidaMapperEF2Model();

            IList<ONGDefinida> ONGsEF = _ONGDefinidaRepository.GetAll();
            List<ONGDefinidaModel> ONGs = new List<ONGDefinidaModel>();
            foreach (ONGDefinida ONGEF in ONGsEF)
            {
                ONGDefinidaModel ong = new ONGDefinidaModel();
                ong = AutoMapper.Mapper.Map(ONGEF, ong);

                ong.Ciudad = ONGEF.Direccion.Ciudad;
                ong.CoordX = ONGEF.Direccion.CoordX;
                ong.CoordY = ONGEF.Direccion.CoordY;
                ong.CP = ONGEF.Direccion.CP;
                ong.Dir = ONGEF.Direccion.Dir;
                ong.Estado = ONGEF.Direccion.Estado;
                ong.Pais = ONGEF.Direccion.Pais;

                ONGs.Add(ong);
            }
            return ONGs;
        }

        public IQueryable<ONGDefinidaModel> Query(Expression<Func<ONGDefinidaModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public long Count(Expression<Func<ONGDefinidaModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public long Count()
        {
            throw new NotImplementedException();
        }
    }
}
